using DG.Tweening.Core;
using DG.Tweening.Plugins.Options;
using System;
using UnityEngine;

namespace DG.Tweening
{
    /// <summary>
    /// DOTween.Sequence中不支持SetSpeedBased
    /// 这里模拟SpeedBase，方法就是先算法时间传入，外部调用传的是速度
    /// </summary>
    public static class DoTweenExtension
    {
        public static TweenerCore<Vector3, Vector3, VectorOptions> DOMoveSpeedBase(this Transform target, Vector3 endValue, float duration, bool snapping = false)
        {
            var changeValue = endValue - target.position;
            duration = Vector3GetSpeedBasedDuration(duration, changeValue);
            return target.DOMove(endValue, duration, snapping);
        }

        public static TweenerCore<Vector3, Vector3, VectorOptions> DOLocalMoveSpeedBase(this Transform target, Vector3 endValue, float duration, bool snapping = false)
        {
            var changeValue = endValue - target.localPosition;
            duration = Vector3GetSpeedBasedDuration(duration, changeValue);
            return target.DOLocalMove(endValue, duration, snapping);
        }

        public static TweenerCore<Quaternion, Vector3, QuaternionOptions> DORotateSpeedBase(this Transform target, Vector3 endValue, float duration, RotateMode mode = RotateMode.Fast)
        {
            var changeValue = endValue - target.eulerAngles;
            duration = Vector3GetSpeedBasedDuration(duration, changeValue);

            return target.DORotate(endValue, duration, mode);
        }

        public static TweenerCore<Quaternion, Quaternion, NoOptions> DORotateQuaternionSpeedBase(this Transform target, Quaternion endValue, float duration)
        {
            var changeValue = endValue.eulerAngles - target.eulerAngles;
            duration = Vector3GetSpeedBasedDuration(duration, changeValue);

            return target.DORotateQuaternion(endValue, duration);
        }

        #region calculator
        private static float CircleGetSpeedBasedDuration(float unitsXSecond, Vector2 changeValue)
        {
            return changeValue.x / unitsXSecond;
        }

        private static float ColorGetSpeedBasedDuration(float unitsXSecond, Color changeValue)
        {
            return 1f / unitsXSecond;
        }

        private static float DoubleGetSpeedBasedDuration(float unitsXSecond, double changeValue)
        {
            float num = (float)changeValue / unitsXSecond;
            if (num < 0f)
            {
                num = 0f - num;
            }
            return num;
        }

        private static float FloatGetSpeedBasedDuration(float unitsXSecond, float changeValue)
        {
            float num = changeValue / unitsXSecond;
            if (num < 0f)
            {
                num = 0f - num;
            }
            return num;
        }

        private static float IntGetSpeedBasedDuration(float unitsXSecond, int changeValue)
        {
            float num = (float)changeValue / unitsXSecond;
            if (num < 0f)
            {
                num = 0f - num;
            }
            return num;
        }


        private static float LongGetSpeedBasedDuration(float unitsXSecond, long changeValue)
        {
            float num = (float)changeValue / unitsXSecond;
            if (num < 0f)
            {
                num = 0f - num;
            }
            return num;
        }

        private static float UintGetSpeedBasedDuration(float unitsXSecond, uint changeValue)
        {
            float num = (float)changeValue / unitsXSecond;
            if (num < 0f)
            {
                num = 0f - num;
            }
            return num;
        }

        private static float UlongGetSpeedBasedDuration(float unitsXSecond, ulong changeValue)
        {
            float num = (float)changeValue / unitsXSecond;
            if (num < 0f)
            {
                num = 0f - num;
            }
            return num;
        }


        private static float QuaternionGetSpeedBasedDuration(float unitsXSecond, Vector3 changeValue)
        {
            return changeValue.magnitude / unitsXSecond;
        }


        private static float RectOffGetSpeedBasedDuration(float unitsXSecond, RectOffset changeValue)
        {
            float num = changeValue.right;
            if (num < 0f)
            {
                num = 0f - num;
            }
            float num2 = changeValue.bottom;
            if (num2 < 0f)
            {
                num2 = 0f - num2;
            }
            return (float)Math.Sqrt(num * num + num2 * num2) / unitsXSecond;
        }

        private static float RectGetSpeedBasedDuration(float unitsXSecond, Rect changeValue)
        {
            float width = changeValue.width;
            float height = changeValue.height;
            return (float)Math.Sqrt(width * width + height * height) / unitsXSecond;
        }

        private static float Vectoe2GetSpeedBasedDuration(float unitsXSecond, Vector2 changeValue)
        {
            return changeValue.magnitude / unitsXSecond;
        }

        private static float Vector3GetSpeedBasedDuration(float unitsXSecond, Vector3 changeValue)
        {
            return changeValue.magnitude / unitsXSecond;
        }

        private static float Vector4GetSpeedBasedDuration(float unitsXSecond, Vector4 changeValue)
        {
            return changeValue.magnitude / unitsXSecond;
        }
        #endregion

    }
}
